/*
 * Copyright (c) 2018-2020 Baidu.com, Inc. All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.baidubce.services.bcc.model.instance;

import com.baidubce.auth.BceCredentials;
import com.baidubce.model.AbstractBceRequest;
import com.baidubce.services.bcc.model.Billing;
import com.baidubce.services.bcc.model.CreateCdsModel;
import com.baidubce.services.bcc.model.TagModel;
import com.baidubce.services.bcc.model.volume.EphemeralDisk;
import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.List;

/**
 * The request for creating a newly instance.
 */
public class CreateInstanceRequest extends AbstractBceRequest {

    /**
     * An ASCII string whose length is less than 64.
     *
     * The request will be idempotent if clientToken is provided.
     * If the clientToken is not specified by the user, a random String generated by default algorithm will be used.
     * See more detail at
     * <a href = "https://bce.baidu.com/doc/BCC/API.html#.E5.B9.82.E7.AD.89.E6.80.A7">
     *     BCE API doc</a>
     * When creating the storage optimized instance, one ephemeral disk must be created together.
     */
    @JsonIgnore
    private String clientToken;

    /**
     * The parameter to specified which kind of instance to create, there is default value when null.
     * see all of supported instance type in {@link com.baidubce.services.bcc.model.instance.InstanceType}
     */
    private String instanceType;

    /**
     * The instance of spec.
     */
    private String spec;

    /**
     * The parameter to specified the cpu core to create the instance.
     */
    private int cpuCount;

    /**
     * The parameter to specified the capacity of memory in GB to create the instance.
     */
    private int memoryCapacityInGB;


    /**
     * The parameter to specify the root disk size in GB.The root disk excludes the system disk, available is 40-500GB.
     *
     */
    private int rootDiskSizeInGb;

    /**
     *  The parameter to specify the root disk storage type. Default use of HP1 cloud disk.
     *
     */
    private String rootDiskStorageType;

    /**
     * The optional parameter to specify the ephemeral disk list
     *
     * When creating the storage optimized instance, one ephemeral disk must be created together.
     *
     * When creating the gpu instance, one ephemeral disk must be created together, the optional ephemeral disk size
     * see <a href = "https://cloud.baidu.com/doc/BCC/API.html#.5E.9B.3F.DF.1D.60.51.F5.A2.B0.FC.3D.24.64.A0.8C">
     *     The optional ephemeral disk size for gpu instance</a>
     *
     * When creating the fpga instance, one ephemeral disk must be created together, the optional ephemeral disk size
     * see <a href = "https://cloud.baidu.com/doc/BCC/API.html#.84.A3.73.8E.D2.2E.66.28.54.10.BF.38.C3.94.F7.9A">
     *     The optional ephemeral disk size for gpu instance</a>
     *
     */
    private List<EphemeralDisk> ephemeralDisks;

    /**
     * The optional parameter to specify the ephemeral disk size in GB.
     *
     * The ephemeral disk excludes the system disk, available is 0-500GB
     *
     * This parameter will be deprecated in the future, we suggest using the ephemeralDisks param instead.
     */
    @Deprecated
    private int localDiskSizeInGB;

    /**
     * The optional list of volume detail info to create.
     */
    private List<CreateCdsModel> createCdsList;

    /**
     * The id of image,list all available image
     * in {@link com.baidubce.services.bcc.BccClient#listImages()}
     */
    private String imageId;

    /**
     * The optional parameter to specify the bandwidth in Mbps for the new instance.
     *
     * It must among 0 and 200,default value is 0.
     * If it's specified to 0, it will get the internal ip address only.
     */
    private int networkCapacityInMbps = 0;

    /**
     * The number of instance to buy, the default value is 1.
     */
    private int purchaseCount = 1;

    /**
     * The optional parameter to desc the instance that will be created.
     */
    private String name;

    /**
     * The optional parameter to desc the hostname of instance that will be created.
     */
    private String hostname;

    /**
     * Indicates whether automatic generation of ordered suffixes
     */
    private boolean autoSeqSuffix;

    /**
     * The optional parameter to specify the password for the instance.
     *
     * If specify the adminPass,the adminPass must be a 8-16 characters String which must
     * contains letters,numbers and symbols. The symbols only contains "!@#$%^*()".
     * The adminPass will be encrypted in AES-128 algorithm
     * with the substring of the former 16 characters of user SecretKey.
     *
     * If not specify the adminPass, it will be specified by an random string.
     * See more detail on
     * <a href = "https://bce.baidu.com/doc/BCC/API.html#.7A.E6.31.D8.94.C1.A1.C2.1A.8D.92.ED.7F.60.7D.AF">
     * BCE API doc</a>
     */
    private String adminPass;

    /**
     * The detail model to specify the billing info.
     */
    private Billing billing;

    /**
     * Indicates whether the tag is bound to all relation instances.
     */
    private boolean relationTag;

    /**
     * The list of tag to be bonded.
     */
    private List<TagModel> tags;

    /**
     * specified id of dedicated host when creating dedicated instance
     */
    private String dedicatedHostId;

    /**
     * the name of available zone, optional param
     * through listZones, we can get all available zone info at current region
     * e.g. "cn-gz-a"  "cn-gz-b"
     */
    private String zoneName;

    /**
     * the id of subnet from vpc, optional param, default value is default subnet from default vpc
     */
    private String subnetId;

    /**
     * specify the securityGroupId of creating instance, optional param
     * vpcId of the securityGroupId must be the same as the vpcId of subnetId
     * through listSecurityGroups, we can get all securityGroup info at current region
     */
    private String securityGroupId;

    /**
     * specify the gpuCard info of creating GPU instance,
     * see all of supported gpu card type in {@link com.baidubce.services.bcc.model.instance.GpuCardType}
     */
    private GpuCardType gpuCard;

    /**
     * specify the gpuCard info of creating FPGA instance,
     * see all of supported fpga card type in {@link com.baidubce.services.bcc.model.instance.FpgaCardType}
     */
    private FpgaCardType fpgaCard;

    /**
     * specify the card count for creating GPU/FPGA instance
     */
    private int cardCount = 1;

    /**
     * The id of asp
     */
    private String aspId;

    /**
     * specifying auto renew time length.
     */
    private int autoRenewTime;

    /**
     * specifying auto renew time unit
     */
    private String autoRenewTimeUnit;

    /**
     * Whether the cds is auto renew or not
     */
    private boolean cdsAutoRenew;

    /**
     * The id of the deploymentSet
     */
    private String deployId;

    /**
     * Specified the internet charge type
     */
    private String internetChargeType;

    /**
     * The id of the keypair
     */
    private String keypairId;

    /**
     * Specified the bidding model
     */
    private String bidModel;

    /**
     * Specified the bidding price
     */
    private String bidPrice;

    /**
     * Configure optional client token for the request. The request will be idempotent if client token is provided.
     * If the clientToken is not specified by the user, a random String generated by default algorithm will be used.
     *
     * @param clientToken An ASCII string whose length is less than 64.
     *                    See more detail at
     *                    <a href = "https://bce.baidu.com/doc/BCC/API.html#.E5.B9.82.E7.AD.89.E6.80.A7">
     *                        BCE API doc</a>
     * @return CreateInstanceRequest with specific clientToken
     */
    public CreateInstanceRequest withClientToken(String clientToken) {
        this.setClientToken(clientToken);
        return this;
    }

    public String getClientToken() {
        return clientToken;
    }

    public void setClientToken(String clientToken) {
        this.clientToken = clientToken;
    }

    /**
     * Configure instanceType for the request.
     *
     * @param instanceType The specified Specification to create the instance.
     *                     See more detail on
     * <a href = "https://bce.baidu.com/doc/BCC/API.html#.E5.AE.9E.E4.BE.8B.E5.A5.97.E9.A4.90.E8.A7.84.E6.A0.BC">
     *     BCE API doc</a>
     * @return CreateInstanceRequest with specific instanceType
     */
    public CreateInstanceRequest withInstanceType(String instanceType) {
        this.setInstanceType(instanceType);
        return this;
    }
    public String getInstanceType() {
        return instanceType;
    }

    public void setInstanceType(String instanceType) {
        this.instanceType = instanceType;
    }

    public CreateInstanceRequest withSpec(String Spec) {
        this.setSpec(Spec);
        return this;
    }

    public String getSpec() {
        return spec;
    }

    public void setSpec(String spec) {
        this.spec = spec;
    }

    public CreateInstanceRequest withCpuCount(int cpuCount) {
        this.cpuCount = cpuCount;
        return this;
    }

    public int getCpuCount() {
        return cpuCount;
    }

    public void setCpuCount(int cpuCount) {
        this.cpuCount = cpuCount;
    }

    public CreateInstanceRequest withMemoryCapacityInGB(int memoryCapacityInGB) {
        this.memoryCapacityInGB = memoryCapacityInGB;
        return this;
    }

    public int getMemoryCapacityInGB() {
        return memoryCapacityInGB;
    }

    public void setMemoryCapacityInGB(int memoryCapacityInGB) {
        this.memoryCapacityInGB = memoryCapacityInGB;
    }

    public CreateInstanceRequest withEphemeralDisks(List<EphemeralDisk> ephemeralDisks) {
        this.ephemeralDisks = ephemeralDisks;
        return this;
    }
    public CreateInstanceRequest withRootDiskSizeInGb(int rootDiskSizeInGb) {
        this.rootDiskSizeInGb = rootDiskSizeInGb;
        return this;
    }

    public int getRootDiskSizeInGb() {
        return rootDiskSizeInGb;
    }

    public void setRootDiskSizeInGb(int rootDiskSizeInGb) {
        this.rootDiskSizeInGb = rootDiskSizeInGb;
    }

    public CreateInstanceRequest withRootDiskStorageType(String rootDiskStorageType) {
        this.rootDiskStorageType = rootDiskStorageType;
        return this;
    }
    public String getRootDiskStorageType() {
        return rootDiskStorageType;
    }

    public void setRootDiskStorageType(String rootDiskStorageType) {
        this.rootDiskStorageType = rootDiskStorageType;
    }

    public List<EphemeralDisk> getEphemeralDisks() {
        return ephemeralDisks;
    }

    public void setEphemeralDisks(List<EphemeralDisk> ephemeralDisks) {
        this.ephemeralDisks = ephemeralDisks;
    }

    /**
     * Configure imageId for the request.
     *
     * @param imageId The specified image id to create the instance.
     * @return CreateInstanceRequest with specific imageId
     */
    public CreateInstanceRequest withImageId(String imageId) {
        this.setImageId(imageId);
        return this;
    }

    public String getImageId() {
        return imageId;
    }

    public void setImageId(String imageId) {
        this.imageId = imageId;
    }

    @Deprecated
    public int getLocalDiskSizeInGB() {
        return localDiskSizeInGB;
    }

    @Deprecated
    public void setLocalDiskSizeInGB(int localDiskSizeInGB) {
        this.localDiskSizeInGB = localDiskSizeInGB;
    }

    /**
     * Configure localDiskSizeInGB for the request.
     *
     * @param localDiskSizeInGB The optional parameter to specify the temporary disk size in GB.
     * @return CreateInstanceRequest with specific localDiskSizeInGB
     */
    @Deprecated
    public CreateInstanceRequest withLocalDiskSizeInGB(int localDiskSizeInGB) {
        this.localDiskSizeInGB = localDiskSizeInGB;
        return this;
    }

    public List<CreateCdsModel> getCreateCdsList() {
        return createCdsList;
    }

    public void setCreateCdsList(List<CreateCdsModel> createCdsList) {
        this.createCdsList = createCdsList;
    }


    /**
     * Configure createCdsList for the request.
     *
     * @param createCdsList The optional list of volume detail info to create.
     * @return CreateInstanceRequest with specific createCdsList
     */
    public CreateInstanceRequest withCreateCdsList(List<CreateCdsModel> createCdsList) {
        this.createCdsList = createCdsList;
        return this;
    }

    public int getNetworkCapacityInMbps() {
        return networkCapacityInMbps;
    }

    public void setNetworkCapacityInMbps(int networkCapacityInMbps) {
        this.networkCapacityInMbps = networkCapacityInMbps;
    }

    /**
     * Configure networkCapacityInMbps for the request.
     *
     * @param networkCapacityInMbps The optional parameter to specify the bandwidth in Mbps for the new instance.
     * @return CreateInstanceRequest with specific networkCapacityInMbps
     */
    public CreateInstanceRequest withNetworkCapacityInMbps(int networkCapacityInMbps) {
        this.networkCapacityInMbps = networkCapacityInMbps;
        return this;
    }

    public int getPurchaseCount() {
        return purchaseCount;
    }

    public void setPurchaseCount(int purchaseCount) {
        this.purchaseCount = purchaseCount;
    }

    /**
     * Configure purchaseCount for the request.
     *
     * @param purchaseCount The number of instance to buy, the default value is 1.
     * @return CreateInstanceRequest with specific purchaseCount
     */
    public CreateInstanceRequest withPurchaseCount(int purchaseCount) {
        this.purchaseCount = purchaseCount;
        return this;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHostname() {
        return hostname;
    }

    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    public CreateInstanceRequest withHostname(String hostname) {
        this.hostname = hostname;
        return this;
    }

    public boolean isAutoSeqSuffix() {
        return autoSeqSuffix;
    }

    public void setAutoSeqSuffix(boolean autoSeqSuffix) {
        this.autoSeqSuffix = autoSeqSuffix;
    }

    public CreateInstanceRequest withAutoSeqSuffix(boolean autoSeqSuffix) {
        this.autoSeqSuffix = autoSeqSuffix;
        return this;
    }

    /**
     * Configure name for the request.
     *
     * @param name The optional parameter to desc the instance that will be created.
     * @return CreateInstanceRequest with specific name
     */
    public CreateInstanceRequest withName(String name) {
        this.name = name;
        return this;
    }

    public String getAdminPass() {
        return adminPass;
    }

    public void setAdminPass(String adminPass) {
        this.adminPass = adminPass;
    }

    /**
     * Configure adminPass for the request.
     *
     * @param adminPass The optional parameter to specify the password for the instance.
     *                  The adminPass will be encrypted in AES-128 algorithm
     *                  with the substring of the former 16 characters of user SecretKey.
     *                  See more detail on
     *     <a href = "https://bce.baidu.com/doc/BCC/API.html#.7A.E6.31.D8.94.C1.A1.C2.1A.8D.92.ED.7F.60.7D.AF">
     *                      BCE API doc</a>
     * @return CreateInstanceRequest with specific adminPass
     */
    public CreateInstanceRequest withAdminPass(String adminPass) {
        this.adminPass = adminPass;
        return this;
    }

    public Billing getBilling() {
        return billing;
    }

    public void setBilling(Billing billing) {
        this.billing = billing;
    }

    /**
     * Configure billing for the request.
     *
     * @param billing The detail model to specify the billing.
     * @return CreateInstanceRequest with specific billing
     */
    public CreateInstanceRequest withBilling(Billing billing) {
        this.billing = billing;
        return this;
    }

    public boolean isRelationTag() {
        return relationTag;
    }

    public void setRelationTag(boolean relationTag) {
        this.relationTag = relationTag;
    }

    /**
     * Configure relationTag for the request.
     *
     * @param relationTag Indicates whether the tag is bound to all relation instances.
     * @return CreateInstanceRequest with specific relationTag
     */
    public CreateInstanceRequest withRelationTag(boolean relationTag) {
        this.relationTag = relationTag;
        return this;
    }

    public List<TagModel> getTags() {
        return tags;
    }

    public void setTags(List<TagModel> tags) {
        this.tags = tags;
    }

    /**
     * Configure tags for the request.
     *
     * @param tags The list of tag to be bonded.
     * @return CreateInstanceRequest with specific tags
     */
    public CreateInstanceRequest withTags(List<TagModel> tags) {
        this.tags = tags;
        return this;
    }

    public CreateInstanceRequest withDedicatedHostId(String dedicatedHostId) {
        this.dedicatedHostId = dedicatedHostId;
        return this;
    }

    public String getDedicatedHostId() {
        return dedicatedHostId;
    }

    public void setDedicatedHostId(String dedicatedHostId) {
        this.dedicatedHostId = dedicatedHostId;
    }

    /**
     * Configure the zone name for the request
     * @param zoneName
     * @return CreateInstanceRequest with specified zone name
     */
    public CreateInstanceRequest withZoneName(String zoneName) {
        this.zoneName = zoneName;
        return this;
    }

    public String getZoneName() {
        return zoneName;
    }

    public void setZoneName(String zoneName) {
        this.zoneName = zoneName;
    }

    /**
     * Configure the subnetId for the request
     * @param subnetId
     * @return CreateInstanceRequest with specified subnetId
     */
    public CreateInstanceRequest withSubnetId(String subnetId) {
        this.subnetId = subnetId;
        return this;
    }

    public String getSubnetId() {
        return subnetId;
    }

    public void setSubnetId(String subnetId) {
        this.subnetId = subnetId;
    }

    /**
     * Configure the securityGroupId for the request
     * @param securityGroupId
     * @return CreateInstanceRequest with specified securityGroupId
     */
    public CreateInstanceRequest withSecurityGroupId(String securityGroupId) {
        this.securityGroupId = securityGroupId;
        return this;
    }

    public String getSecurityGroupId() {
        return securityGroupId;
    }

    public void setSecurityGroupId(String securityGroupId) {
        this.securityGroupId = securityGroupId;
    }


    public GpuCardType getGpuCard() {
        return gpuCard;
    }

    public void setGpuCard(GpuCardType gpuCard) {
        this.gpuCard = gpuCard;
    }

    /**
     * Configure the gpuCard for the request,
     * see all of supported gpu card type in {@link com.baidubce.services.bcc.model.instance.GpuCardType}
     * @param gpuCard
     * @return CreateInstanceRequest with specified gpuCard
     */
    public CreateInstanceRequest withGpuCard(GpuCardType gpuCard) {
        this.gpuCard = gpuCard;
        return this;
    }

    public FpgaCardType getFpgaCard() {
        return fpgaCard;
    }

    public void setFpgaCard(FpgaCardType fpgaCard) {
        this.fpgaCard = fpgaCard;
    }

    /**
     * Configure the fpgaCard for the request,
     * see all of supported fpga card type in {@link com.baidubce.services.bcc.model.instance.FpgaCardType}
     * @param fpgaCard
     * @return CreateInstanceRequest with specified fpgaCard
     */
    public CreateInstanceRequest withFpgaCard(FpgaCardType fpgaCard) {
        this.fpgaCard = fpgaCard;
        return this;
    }

    public int getCardCount() {
        return cardCount;
    }

    public void setCardCount(int cardCount) {
        this.cardCount = cardCount;
    }

    /**
     * Configure the card count of gpuCardType or gpgaCardType for the request,
     * if creating gpu / fpga instance, one or more card count must be specified.
     * @param cardCount
     * @return CreateInstanceRequest with card count of gpuCardType or gpgaCardTyp.
     */
    public CreateInstanceRequest withCardCount(int cardCount) {
        this.cardCount = cardCount;
        return this;
    }

    public String getAspId() {
        return aspId;
    }

    public void setAspId(String aspId) {
        this.aspId = aspId;
    }

    /**
     * Configure the aspId for the request
     * @param aspId The id of the asp.
     * @return CreateInstanceRequest with specified aspId
     */
    public CreateInstanceRequest withAspId(String aspId) {
        this.aspId = aspId;
        return this;
    }

    public int getAutoRenewTime() {
        return autoRenewTime;
    }

    public void setAutoRenewTime(int autoRenewTime) {
        this.autoRenewTime = autoRenewTime;
    }

    /**
     * Configure the autoRenewTime for the request
     * @param autoRenewTime The specified auto renew time length.
     * @return CreateInstanceRequest with specified autoRenewTime
     */
    public CreateInstanceRequest withAutoRenewTime(int autoRenewTime) {
        this.autoRenewTime = autoRenewTime;
        return this;
    }

    public String getAutoRenewTimeUnit() {
        return autoRenewTimeUnit;
    }

    public void setAutoRenewTimeUnit(String autoRenewTimeUnit) {
        this.autoRenewTimeUnit = autoRenewTimeUnit;
    }

    /**
     * Configure the autoRenewTimeUnit for the request
     * @param autoRenewTimeUnit The specified auto renew time unit. The unit can be "month" or "year".
     * @return CreateInstanceRequest with specified autoRenewTimeUnit
     */
    public CreateInstanceRequest withAutoRenewTimeUnit(String autoRenewTimeUnit) {
        this.autoRenewTimeUnit = autoRenewTimeUnit;
        return this;
    }

    public boolean isCdsAutoRenew() {
        return cdsAutoRenew;
    }

    public void setCdsAutoRenew(boolean cdsAutoRenew) {
        this.cdsAutoRenew = cdsAutoRenew;
    }

    /**
     * Configure the cdsAutoRenew for the request
     * @param cdsAutoRenew The option param to indicate that whether the cds is auto renew or not.
     *                     If <code>true<code/>, it means the instance is auto renew.
     * @return CreateInstanceRequest with specified cdsAutoRenew
     */
    public CreateInstanceRequest withCdsAutoRenew(boolean cdsAutoRenew) {
        this.cdsAutoRenew = cdsAutoRenew;
        return this;
    }

    public String getDeployId() {
        return deployId;
    }

    public void setDeployId(String deployId) {
        this.deployId = deployId;
    }

    /**
     * Configure the deployId for the request
     * @param deployId The specified deployment set id.
     * @return CreateInstanceRequest with specified deployId
     */
    public CreateInstanceRequest withDeployId(String deployId) {
        this.deployId = deployId;
        return this;
    }

    public String getInternetChargeType() {
        return internetChargeType;
    }

    public void setInternetChargeType(String internetChargeType) {
        this.internetChargeType = internetChargeType;
    }

    /**
     * Configure the internetChargeType for the request
     * @param internetChargeType The specified internet charge type.
     * @return CreateInstanceRequest with specified internetChargeType
     */
    public CreateInstanceRequest withInternetChargeType(String internetChargeType) {
        this.internetChargeType = internetChargeType;
        return this;
    }

    public String getKeypairId() {
        return keypairId;
    }

    public void setKeypairId(String keypairId) {
        this.keypairId = keypairId;
    }

    /**
     * Configure the keypairId for the request
     * @param keypairId The specified keypair id.
     * @return CreateInstanceRequest with specified keypairId
     */
    public CreateInstanceRequest withKeypairId(String keypairId) {
        this.keypairId = keypairId;
        return this;
    }

    public String getBidModel() {
        return bidModel;
    }

    public void setBidModel(String bidModel) {
        this.bidModel = bidModel;
    }

    /**
     * Configure the bidModel for the request
     * @param bidModel The specified bidModel. The value can be "market" or "custom".
     * @return CreateInstanceRequest with specified bidModel
     */
    public CreateInstanceRequest withBidModel(String bidModel) {
        this.bidModel = bidModel;
        return this;
    }

    public String getBidPrice() {
        return bidPrice;
    }

    public void setBidPrice(String bidPrice) {
        this.bidPrice = bidPrice;
    }

    /**
     * Configure the bidPrice for the request
     * @param bidPrice The specified bidPrice. Only the value of bidModel is custom, the param works.
     * @return CreateInstanceRequest with specified bidPrice
     */
    public CreateInstanceRequest withBidPrice(String bidPrice) {
        this.bidPrice = bidPrice;
        return this;
    }

    /**
     * Configure request credential for the request.
     *
     * @param credentials a valid instance of BceCredentials.
     * @return CreateInstanceRequest with credentials.
     */
    public CreateInstanceRequest withRequestCredentials(BceCredentials credentials) {
        this.setRequestCredentials(credentials);
        return this;
    }


}
